package com.developer.platform.infrastructure.repository;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.developer.platform.domain.NoticeAggregateRoot;
import com.developer.platform.domain.repository.INoticeRepository;
import com.developer.platform.infrastructure.data.mapper.NoticeMapper;
import com.developer.platform.infrastructure.data.mapper.NoticeSystemMapper;
import com.developer.platform.infrastructure.data.mapper.NoticeUserMapper;
import com.developer.platform.infrastructure.data.po.Notice;
import com.developer.platform.infrastructure.data.po.NoticeSystem;
import com.developer.platform.infrastructure.data.po.NoticeUser;
import com.developer.platform.infrastructure.enums.NoticeUserType;
import com.developer.platform.infrastructure.enums.StatusEnum;
import com.developer.platform.infrastructure.enums.SystemType;
import com.google.common.collect.Lists;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.stereotype.Repository;

/**
 * @author ：qiaoliang
 * @date ：2020-11-10
 */
@Repository
public class NoticeRepository implements INoticeRepository {

    private final NoticeMapper noticeMapper;
    private final NoticeUserMapper noticeUserMapper;
    private final NoticeSystemMapper noticeSystemMapper;

    public NoticeRepository(NoticeMapper noticeMapper,
        NoticeUserMapper noticeUserMapper,
        NoticeSystemMapper noticeSystemMapper) {
        this.noticeMapper = noticeMapper;
        this.noticeUserMapper = noticeUserMapper;
        this.noticeSystemMapper = noticeSystemMapper;
    }

    @Override
    public NoticeAggregateRoot findById(long id) {
        return noticeMapper.selectById(id);
    }

    @Override
    public void save(NoticeAggregateRoot noticeAggregateRoot) {
        Notice notice = new Notice();
        BeanUtil.copyProperties(noticeAggregateRoot, notice);
        noticeMapper.insert(notice);
        noticeAggregateRoot.setId(notice.getId());
        this.saveData(noticeAggregateRoot);
    }

    @Override
    public void update(NoticeAggregateRoot noticeAggregateRoot) {
        Notice notice = new Notice();
        BeanUtil.copyProperties(noticeAggregateRoot, notice);
        noticeMapper.updateById(notice);
        this.deleteData(noticeAggregateRoot.getId());
        this.saveData(noticeAggregateRoot);
    }

    @Override
    public void delete(long id) {
        noticeMapper.deleteById(id);
        this.deleteData(id);
    }

    @Override
    public void updateStatus(List<Long> ids) {
        Notice notice = new Notice();
        notice.setStatus(StatusEnum.Y);
        LambdaQueryWrapper<Notice> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.in(Notice::getId, ids);
        noticeMapper.update(notice, lambdaQueryWrapper);
    }

    private void deleteData(long noticeId){
        LambdaQueryWrapper<NoticeUser> userLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userLambdaQueryWrapper.eq(NoticeUser::getNoticeId, noticeId);
        noticeUserMapper.delete(userLambdaQueryWrapper);

        LambdaQueryWrapper<NoticeSystem> systemLambdaQueryWrapper = new LambdaQueryWrapper<>();
        systemLambdaQueryWrapper.eq(NoticeSystem::getNoticeId, noticeId);
        noticeSystemMapper.delete(systemLambdaQueryWrapper);
    }

    private void saveData(NoticeAggregateRoot notice){
        List<NoticeSystem> noticeSystems = Lists.newLinkedList();
        if(CollUtil.isNotEmpty(notice.getInfluenceIds())){
            noticeSystems.addAll(notice.getInfluenceIds().parallelStream()
                .map(id -> new NoticeSystem(notice.getId(), id, SystemType.S))
                .collect(Collectors.toList()));
        }
        if(CollUtil.isNotEmpty(notice.getSystemIds())){
            noticeSystems.addAll(notice.getSystemIds().parallelStream()
                .map(id -> new NoticeSystem(notice.getId(), id, SystemType.G))
                .collect(Collectors.toList()));
        }
        List<NoticeUser> noticeUserList = Lists.newLinkedList();
        if(CollUtil.isNotEmpty(notice.getDurationUserIds())){
            noticeUserList.addAll(notice.getDurationUserIds().parallelStream()
                .map(id -> new NoticeUser(id, notice.getId(), NoticeUserType.U))
                .collect(Collectors.toList()));
        }
        if(CollUtil.isNotEmpty(notice.getNoticeUserIds())){
            noticeUserList.addAll(notice.getNoticeUserIds().parallelStream()
                .map(id -> new NoticeUser(id, notice.getId(), NoticeUserType.T))
                .collect(Collectors.toList()));
        }
        if(CollUtil.isNotEmpty(notice.getTellUserIds())){
            noticeUserList.addAll(notice.getTellUserIds().parallelStream()
                .map(id -> new NoticeUser(id, notice.getId(), NoticeUserType.D))
                .collect(Collectors.toList()));
        }
        if(CollUtil.isNotEmpty(notice.getDateUserIds())){
            noticeUserList.addAll(notice.getDateUserIds().parallelStream()
                .map(id -> new NoticeUser(id, notice.getId(), NoticeUserType.M))
                .collect(Collectors.toList()));
        }
        if(CollUtil.isNotEmpty(noticeSystems)){
            noticeSystems.forEach(noticeSystemMapper::insert);
        }
        if(CollUtil.isNotEmpty(noticeUserList)){
            noticeUserList.forEach(noticeUserMapper::insert);
        }

    }

}
